/**
  ******************************************************************************
  * @file    tc32l010_lpuart.c
  * @author  CHIPAT Application Team
  * @brief   This file provides firmware functions to manage the following
  *          functionalities of the Low Power UART (LPUART) peripheral:
  *           + Initialization functions.
  *           + Configuration functions.
  *           + Interrupts and flags management functions.
  @verbatim
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "tc32l010_lpuart.h"



/** @defgroup LPUART
  * @brief LPUART module driver.
  * @{
  */

/* External variables --------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
/*!< LPUART CR1 register clear Mask */
#define LPUART_CR1_CLEAR_MASK            ((uint32_t)(LPUART_CR1_M | LPUART_CR1_PCE | \
                                                     LPUART_CR1_PS | LPUART_CR1_TE | \
                                                     LPUART_CR1_RE))
/*!< LPUART CR2 register clear Mask */
#define LPUART_CR2_CLEAR_MASK            ((uint32_t)(LPUART_CR2_STOP | LPUART_CR2_SWAP | \
                                                     LPUART_CR2_RXINV | LPUART_CR2_TXINV | \
                                                     LPUART_CR2_DATAINV | LPUART_CR2_MSBFIRST))

/*!< LPUART Interrupts mask */
#define LPUART_IT_MASK                   ((uint16_t)0x001F)


/**
  * @brief  Deinitializes the LPUARTx peripheral registers to their default reset values.
  * @param  LPUARTx: where x can be 0.
  * @retval None
  *
  */
void LPUART_DeInit(LPUART_TypeDef* LPUARTx)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));

    /* Deinitializes the LPUARTx peripheral */
    if(LPUARTx == LPUART0)
    {
        RCC_APBPeriphResetCmd(RCC_APBPeriph_LPUART0, ENABLE);
        RCC_APBPeriphResetCmd(RCC_APBPeriph_LPUART0, DISABLE);
    }
}

/**
  * @brief  Initializes the LPUARTx peripheral according to the specified parameters
  *         in the LPUART_InitStruct.
  * @param  LPUARTx: where x can be 0.
  * @param  LPUART_InitStruct: pointer to an LPUART_InitTypeDef structure that contains
  *         the configuration information for the specified LPUART peripheral.
  * @retval None
  *
  * @note   It is mandatory to disable the peripheral to use this function.
  */
void LPUART_Init(LPUART_TypeDef* LPUARTx, LPUART_InitTypeDef* LPUART_InitStruct)
{
    uint32_t tmpreg = 0x00;
    uint32_t integerdivider = 0x00;
    uint32_t fractionaldivider = 0x00;
    RCC_ClocksTypeDef RCC_ClocksStatus;

    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_LPUART_BAUDRATE(LPUART_InitStruct->LPUART_BaudRate));
    assert_param(IS_LPUART_WORD_LENGTH(LPUART_InitStruct->LPUART_WordLength));
    assert_param(IS_LPUART_STOPBITS(LPUART_InitStruct->LPUART_StopBits));
    assert_param(IS_LPUART_PARITY(LPUART_InitStruct->LPUART_Parity));
    assert_param(IS_LPUART_MODE(LPUART_InitStruct->LPUART_Mode));
    assert_param(IS_LPUART_HARDWARE_FLOW_CONTROL(LPUART_InitStruct->LPUART_HardwareFlowControl));
    assert_param(IS_LPUART_FIRST_BIT(LPUART_InitStruct->LPUART_FirstBit));
    assert_param(IS_LPUART_DATAINV(LPUART_InitStruct->LPUART_DataInv));
    assert_param(IS_LPUART_TXINV(LPUART_InitStruct->LPUART_TxPinInv));
    assert_param(IS_LPUART_RXINV(LPUART_InitStruct->LPUART_RxPinInv));
    assert_param(IS_LPUART_SWAP_EN(LPUART_InitStruct->LPUART_SwapTxRx));

    /*---------------------------- LPUART CR2 Configuration -----------------------*/
    tmpreg = LPUARTx->CR2;

    /* Clear STOP[13:12], SWAP, RXINV, TXINV, DATAINV and MSB bits */
    tmpreg &= (uint32_t)~(LPUART_CR2_CLEAR_MASK);

    /* Configure the LPUART Stop Bits:
        Set STOP[13:12], SWAP, RXINV, TXINV, DATAINV and MSB bits according to LPUART_StopBits value */
    tmpreg |= (uint32_t)(LPUART_InitStruct->LPUART_StopBits|(LPUART_InitStruct->LPUART_FirstBit<<19)|\
                         (LPUART_InitStruct->LPUART_DataInv<<18)|(LPUART_InitStruct->LPUART_TxPinInv<<17)|\
                         (LPUART_InitStruct->LPUART_RxPinInv<<16)|(LPUART_InitStruct->LPUART_SwapTxRx<<15));

    /* Write to LPUART CR2 */
    LPUARTx->CR2 = tmpreg;

    /*---------------------------- LPUART CR1 Configuration -----------------------*/
    tmpreg = LPUARTx->CR1;

    /* Clear M, PCE, PS, Float, TE and RE bits */
    tmpreg &= (uint32_t)~(LPUART_CR1_CLEAR_MASK);

    /* Configure the LPUART Word Length, Parity and mode:
       Set the M bits according to LPUART_WordLength value
       Set PCE and PS bits according to LPUART_Parity value
       Set TE and RE bits according to LPUART_Mode value */
    tmpreg |= (uint32_t)LPUART_InitStruct->LPUART_WordLength | LPUART_InitStruct->LPUART_Parity |
              LPUART_InitStruct->LPUART_Mode;

    /* Write to LPUART CR1 */
    LPUARTx->CR1 = tmpreg;

    /*---------------------------- LPUART CR3 Configuration -----------------------*/
    tmpreg = LPUARTx->CR3;

    /* Clear CTSE and RTSE bits */
    tmpreg &= (uint32_t)~(LPUART_CR3_RTSE | LPUART_CR3_CTSE);

    /* Configure the LPUART HFC :
        Set CTSE and RTSE bits according to LPUART_HardwareFlowControl value */
    tmpreg |= LPUART_InitStruct->LPUART_HardwareFlowControl;

    /* Write to LPUART CR3 */
    LPUARTx->CR3 = tmpreg;

    /*---------------------------- LPUART BRR Configuration -----------------------*/
    /* Configure the LPUART Baud Rate */
    RCC_GetClocksFreq(&RCC_ClocksStatus);

    integerdivider = RCC_ClocksStatus.LPUARTCLK_Frequency*100 / (LPUART_InitStruct->LPUART_BaudRate);

    tmpreg = (integerdivider / 100) << 4;

    /* Determine the fractional part */
    fractionaldivider = integerdivider - (100 * (tmpreg >> 4));

    tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F);

    /* Write to LPUART BRR register */
    LPUARTx->BRR = tmpreg;
}

/**
  * @brief  Fills each LPUART_InitStruct member with its default value.
  * @param  LPUART_InitStruct: pointer to a LPUART_InitTypeDef structure which will
  *         be initialized.
  * @retval None
  */
void LPUART_StructInit(LPUART_InitTypeDef* LPUART_InitStruct)
{
    /* LPUART_InitStruct members default value */
    LPUART_InitStruct->LPUART_BaudRate = 9600;
    LPUART_InitStruct->LPUART_WordLength = LPUART_WordLength_8b;
    LPUART_InitStruct->LPUART_StopBits = LPUART_StopBits_1;
    LPUART_InitStruct->LPUART_Parity = LPUART_Parity_No ;
    LPUART_InitStruct->LPUART_Mode = LPUART_Mode_Rx | LPUART_Mode_Tx;
    LPUART_InitStruct->LPUART_HardwareFlowControl = LPUART_HardwareFlowControl_None;
    LPUART_InitStruct->LPUART_FirstBit = LPUART_FirstBit_LSB;
    LPUART_InitStruct->LPUART_DataInv = LPUART_DataInversion_Disable;
    LPUART_InitStruct->LPUART_TxPinInv = LPUART_TxInversion_Disable;
    LPUART_InitStruct->LPUART_RxPinInv = LPUART_RxInversion_Disable;
    LPUART_InitStruct->LPUART_SwapTxRx = LPUART_SwapTxRx_Disable;
}

/**
  * @brief  Enables or disables the specified LPUART peripheral.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  NewState: new state of the LPUARTx peripheral.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void LPUART_Cmd(LPUART_TypeDef* LPUARTx, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the selected LPUART by setting the UE bit in the CR1 register */
        LPUARTx->CR1 |= LPUART_CR1_UE;
    }
    else
    {
        /* Disable the selected LPUART by clearing the UE bit in the CR1 register */
        LPUARTx->CR1 &= (uint32_t)~((uint32_t)LPUART_CR1_UE);
    }
}

/**
  * @}
  */

/**
  * @brief  Transmits single data through the LPUARTx peripheral.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  Data: the data to transmit.
  * @retval None
  */
void LPUART_SendData(LPUART_TypeDef* LPUARTx, uint16_t Data)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_LPUART_DATA(Data));

    /* Transmit Data */
    LPUARTx->DR = (Data & (uint16_t)0x01FF);
}

/**
  * @brief  Returns the most recent received data by the LPUARTx peripheral.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @retval The received data.
  */
uint16_t LPUART_ReceiveData(LPUART_TypeDef* LPUARTx)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));

    /* Receive Data */
    return (uint16_t)(LPUARTx->DR & (uint16_t)0x01FF);
}

/**
  * @}
  */

/**
  * @brief  Sets the address of the LPUART node.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  LPUART_Address: Indicates the address of the LPUART node.
  * @param  LPUART_AddressWidth: This parameter can be:
  *                              LPUART_AddressWidth_4Bits or LPUART_AddressWidth_7Bits.
  * @retval None
  */
void LPUART_SetAddress(LPUART_TypeDef* LPUARTx, uint8_t LPUART_Address, uint8_t LPUART_AddressWidth)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_LPUART_ADDRESS(LPUART_Address));
    assert_param(IS_LPUART_ADDRESSWIDTH(LPUART_AddressWidth));

    /* Clear the LPUART address */
    LPUARTx->CR2 &= (uint32_t)~((uint32_t)(LPUART_CR2_ADDL | LPUART_CR2_ADDH |LPUART_CR2_ADDM7));
    /* Set the LPUART address node */
    LPUARTx->CR2 |= ((LPUART_Address << 24) | LPUART_AddressWidth);
}

/**
  * @brief  Determines if the LPUART is in mute mode or not.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  NewState: new state of the LPUART mute mode.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void LPUART_ReceiverWakeUpCmd(LPUART_TypeDef* LPUARTx, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the LPUART mute mode  by setting the RWU bit in the CR1 register */
        LPUARTx->CR1 |= LPUART_CR1_RWU;
    }
    else
    {
        /* Disable the LPUART mute mode by clearing the RWU bit in the CR1 register */
        LPUARTx->CR1 &= (uint32_t)~(LPUART_CR1_RWU);
    }
}

/**
  * @brief  Selects the LPUART WakeUp method.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  LPUART_WakeUp: specifies the LPUART wakeup method.
  *          This parameter can be one of the following values:
  *            @arg LPUART_WakeUp_IdleLine: WakeUp by an idle line detection
  *            @arg LPUART_WakeUp_AddressMark: WakeUp by an address mark
  * @retval None
  */
void LPUART_WakeUpConfig(LPUART_TypeDef* LPUARTx, uint16_t LPUART_WakeUp)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_LPUART_WAKEUP(LPUART_WakeUp));

    LPUARTx->CR1 &= (uint32_t)~(LPUART_CR1_WAKE);
    LPUARTx->CR1 |= LPUART_WakeUp;
}

/**
  * @brief  Enable in stop mode.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  NewState: new state of the LPUARTx peripheral.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void LPUART_StopModeCmd(LPUART_TypeDef* LPUARTx, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the selected LPUART by setting the UESM bit in the CR1 register */
        LPUARTx->CR1 |= LPUART_CR1_UESM;
    }
    else
    {
        /* Disable the selected LPUART by clearing the UESM bit in the CR1 register */
        LPUARTx->CR1 &= ~LPUART_CR1_UESM;
    }
}

/**
  * @brief  Selects the LPUART wakeup method from the Stop Mode.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  LPUART_WakeUp: specifies the LPUART wakeup method.
  *          This parameter can be one of the following values:
  *            @arg LPUART_WakeUp_From_AddrMatch: WakeUp by an address mark
  *            @arg LPUART_WakeUp_From_StartCheck: WakeUp by an Start bit
  *            @arg LPUART_WakeUp_From_RXNE: WakeUp by RXNE
  * @retval None
  */
void LPUART_StopModeConfig(LPUART_TypeDef* LPUARTx, uint8_t LPUART_WakeUp)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_LPUART_WAKEUP_FSTOP(LPUART_WakeUp));

    LPUARTx->CR3 &= (uint32_t)~(LPUART_CR3_WUS);
    LPUARTx->CR3 |= (LPUART_WakeUp << 20);
}

/**
  * @brief  Set the RS485 Driver Enable Mode and polarity.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  LPUART_DEPolarity: .
  *          This parameter can be one of the following values:0~1.
  * @param  LPUART_DEMode: .
  *          This parameter can be one of the following values:0~1.
  * @retval None
  */
void LPUART_RS485DriverEnableConfig(LPUART_TypeDef* LPUARTx, uint8_t LPUART_DEPolarity, uint8_t LPUART_DEMode)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_LPUART_RS485DRIVER_ENABLE_POLARITY(LPUART_DEPolarity));
    assert_param(IS_LPUART_RS485DRIVER_ENABLE_MODE(LPUART_DEMode));

    LPUARTx->CR3 &= (uint32_t)~(LPUART_CR3_DEP | LPUART_CR3_DEM);
    LPUARTx->CR3 |= (LPUART_DEPolarity << 15) | (LPUART_DEMode << 14);
}

/**
  * @brief  Set the RS485 Driver Enable assertion and deassertion time.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  LPUART_AssertionTime: .
  *          This parameter can be one of the following values:0~31.
  * @param  LPUART_DeassertionTime: .
  *          This parameter can be one of the following values:0~31.
  * @retval None
  */
void LPUART_RS485DriverEnableTimeConfig(LPUART_TypeDef* LPUARTx, uint8_t LPUART_AssertionTime, uint8_t LPUART_DeassertionTime)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_LPUART_RS485DRIVER_ENABLE_TIME(LPUART_AssertionTime));
    assert_param(IS_LPUART_RS485DRIVER_ENABLE_TIME(LPUART_DeassertionTime));

    LPUARTx->CR1 &= (uint32_t)~(LPUART_CR1_DEAT | LPUART_CR1_DEDT);
    LPUARTx->CR1 |= (LPUART_AssertionTime << 21) | (LPUART_DeassertionTime << 16);
}

/**
  * @brief  Transmits break characters.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @retval None
  */
void LPUART_SendBreak(LPUART_TypeDef* LPUARTx)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));

    /* Send break characters */
    LPUARTx->CR1 |= LPUART_CR1_SBK;
}

/**
  * @brief  Enables or disables the overrun status.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  NewState: new state of the Overrun.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void LPUART_OVRCmd(LPUART_TypeDef* LPUARTx, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the selected LPUART by setting the OVRDIS bit in the CR3 register */
        LPUARTx->CR3 &= ~LPUART_CR3_OVRDIS;
    }
    else
    {
        /* Disable the selected LPUART by clearing the OVRDIS bit in the CR3 register */
        LPUARTx->CR3 |= LPUART_CR3_OVRDIS;
    }
}

/**
  * @}
  */

/**
  * @brief  Enables or disables the LPUART's Half Duplex communication.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  NewState: new state of the LPUART Communication.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void LPUART_HalfDuplexCmd(LPUART_TypeDef* LPUARTx, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the Half-Duplex mode by setting the HDSEL bit in the CR3 register */
        LPUARTx->CR3 |= LPUART_CR3_HDSEL;
    }
    else
    {
        /* Disable the Half-Duplex mode by clearing the HDSEL bit in the CR3 register */
        LPUARTx->CR3 &= ~(LPUART_CR3_HDSEL);
    }
}

/**
  * @}
  */


/**
  * @}
  */

/**
  * @brief  Enables or disables the LPUART's DMA interface.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  LPUART_DMAReq: specifies the DMA request.
  *          This parameter can be any combination of the following values:
  *            @arg LPUART_DMAReq_Tx: LPUART DMA transmit request
  *            @arg LPUART_DMAReq_Rx: LPUART DMA receive request
  * @param  NewState: new state of the DMA Request sources.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void LPUART_DMACmd(LPUART_TypeDef* LPUARTx, uint16_t LPUART_DMAReq, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_LPUART_DMAREQ(LPUART_DMAReq));
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    if (NewState != DISABLE)
    {
        /* Enable the DMA transfer for selected requests by setting the DMAT and/or
           DMAR bits in the LPUART CR3 register */
        LPUARTx->CR3 |= LPUART_DMAReq;
    }
    else
    {
        /* Disable the DMA transfer for selected requests by clearing the DMAT and/or
           DMAR bits in the LPUART CR3 register */
        LPUARTx->CR3 &= ~LPUART_DMAReq;
    }
}


/**
  * @}
  */

/**
  * @brief  Enables or disables the specified LPUART interrupts.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  LPUART_IT: specifies the LPUART interrupt sources to be enabled or disabled.
  *          This parameter can be one of the following values:
  *            @arg LPUART_IT_CTS:  CTS change interrupt
  *            @arg LPUART_IT_LBD:  LIN Break detection interrupt
  *            @arg LPUART_IT_TXE:  Transmit Data Register empty interrupt
  *            @arg LPUART_IT_TC:   Transmission complete interrupt
  *            @arg LPUART_IT_RXNE: Receive Data register not empty interrupt
  *            @arg LPUART_IT_IDLE: Idle line detection interrupt
  *            @arg LPUART_IT_PE:   Parity Error interrupt
  *            @arg LPUART_IT_ERR:  Error interrupt(Frame error, noise error, overrun error)
  * @param  NewState: new state of the specified LPUARTx interrupts.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void LPUART_ITConfig(LPUART_TypeDef* LPUARTx, uint32_t LPUART_IT, FunctionalState NewState)
{
    uint32_t usartreg = 0x00, itpos = 0x00, itmask = 0x00;
    uint32_t usartxbase = 0x00;
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_LPUART_CONFIG_IT(LPUART_IT));
    assert_param(IS_FUNCTIONAL_STATE(NewState));

    usartxbase = (uint32_t)LPUARTx;

    /* Get the LPUART register index */
    usartreg = (((uint8_t)LPUART_IT) >> 0x05);

    /* Get the interrupt position */
    itpos = LPUART_IT & LPUART_IT_MASK;
    itmask = (((uint32_t)0x01) << itpos);

    if (usartreg == 0x01) /* The IT is in CR1 register */
    {
        usartxbase += 0x0C;
    }
    else if (usartreg == 0x02) /* The IT is in CR2 register */
    {
        usartxbase += 0x10;
    }
    else /* The IT is in CR3 register */
    {
        usartxbase += 0x14;
    }
    if (NewState != DISABLE)
    {
        *(__IO uint32_t*)usartxbase  |= itmask;
    }
    else
    {
        *(__IO uint32_t*)usartxbase &= ~itmask;
    }
}

/**
  * @brief  Checks whether the specified LPUART flag is set or not.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  LPUART_FLAG: specifies the flag to check.
  *          This parameter can be one of the following values:
  *            @arg LPUART_FLAG_CTSI:  CTS Change interrupt flag
  *            @arg LPUART_FLAG_CTS:  CTS flag
  *            @arg LPUART_FLAG_CM:  Character match flag.
  *            @arg LPUART_FLAG_WU:  Wakeup from stop flag.
  *            @arg LPUART_FLAG_TXE:  Transmit data register empty flag
  *            @arg LPUART_FLAG_TC:   Transmission Complete flag
  *            @arg LPUART_FLAG_RXNE: Receive data register not empty flag
  *            @arg LPUART_FLAG_IDLE: Idle Line detection flag
  *            @arg LPUART_FLAG_ORE:  OverRun Error flag
  *            @arg LPUART_FLAG_NE:   Noise Error flag
  *            @arg LPUART_FLAG_FE:   Framing Error flag
  *            @arg LPUART_FLAG_PE:   Parity Error flag
  *            @arg LPUART_FLAG_BUSY:   Busy flag
  *            @arg LPUART_FLAG_TEACK:  Receive enable acknowledge flag
  *            @arg LPUART_FLAG_REACK:  Transmit enable acknowledge flag
  * @retval The new state of LPUART_FLAG (SET or RESET).
  */
FlagStatus LPUART_GetFlagStatus(LPUART_TypeDef* LPUARTx, uint32_t LPUART_FLAG)
{
    FlagStatus bitstatus = RESET;
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_LPUART_FLAG(LPUART_FLAG));

    if ((LPUARTx->SR & LPUART_FLAG) != (uint32_t)RESET)
    {
        bitstatus = SET;
    }
    else
    {
        bitstatus = RESET;
    }
    return bitstatus;
}

/**
  * @brief  Clears the LPUARTx's pending flags.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  LPUART_FLAG: specifies the flag to clear.
  *          This parameter can be any combination of the following values:
  *            @arg LPUART_FLAG_CTSI:  CTS Change flag
  *            @arg LPUART_FLAG_CM:  Character match flag.
  *            @arg LPUART_FLAG_WU:  Wakeup from stop flag.
  *            @arg LPUART_FLAG_TC:   Transmission Complete flag.
  *            @arg LPUART_FLAG_RXNE: Receive data register not empty flag.
  *
  * @note   PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun
  *          error) and IDLE (Idle line detected) flags are cleared by software
  *          sequence: a read operation to LPUART_SR register (LPUART_GetFlagStatus())
  *          followed by a read operation to LPUART_DR register (LPUART_ReceiveData()).
  * @note   RXNE flag can be also cleared by a read to the LPUART_DR register
  *          (LPUART_ReceiveData()).
  * @note   TC flag can be also cleared by software sequence: a read operation to
  *          LPUART_SR register (LPUART_GetFlagStatus()) followed by a write operation
  *          to LPUART_DR register (LPUART_SendData()).
  * @note   TXE flag is cleared only by a write to the LPUART_DR register
  *          (LPUART_SendData()).
  *
  * @retval None
  */
void LPUART_ClearFlag(LPUART_TypeDef* LPUARTx, uint32_t LPUART_FLAG)
{
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_LPUART_CLEAR_FLAG(LPUART_FLAG));

    LPUARTx->SR = (uint32_t)~LPUART_FLAG;
}

/**
  * @brief  Checks whether the specified LPUART interrupt has occurred or not.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  LPUART_IT: specifies the LPUART interrupt source to check.
  *          This parameter can be one of the following values:
  *            @arg LPUART_IT_CTSI:  CTS change interrupt
  *            @arg LPUART_IT_CM:  Character match interrupt
  *            @arg LPUART_IT_WU:  Wakeup from stop mode interrupt
  *            @arg LPUART_IT_TXE:  Transmit Data Register empty interrupt
  *            @arg LPUART_IT_TC:   Transmission complete interrupt
  *            @arg LPUART_IT_RXNE: Receive Data register not empty interrupt
  *            @arg LPUART_IT_IDLE: Idle line detection interrupt
  *            @arg LPUART_IT_ORE_RX : OverRun Error interrupt if the RXNEIE bit is set
  *            @arg LPUART_IT_ORE_ER : OverRun Error interrupt if the EIE bit is set
  *            @arg LPUART_IT_NE:   Noise Error interrupt
  *            @arg LPUART_IT_FE:   Framing Error interrupt
  *            @arg LPUART_IT_PE:   Parity Error interrupt
  * @retval The new state of LPUART_IT (SET or RESET).
  */
ITStatus LPUART_GetITStatus(LPUART_TypeDef* LPUARTx, uint32_t LPUART_IT)
{
    uint32_t bitpos = 0x00, itmask = 0x00, usartreg = 0x00;
    ITStatus bitstatus = RESET;
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_LPUART_GET_IT(LPUART_IT));

    /* Get the LPUART register index */
    usartreg = (((uint8_t)LPUART_IT) >> 0x05);
    /* Get the interrupt position */
    itmask = LPUART_IT & LPUART_IT_MASK;
    itmask = (uint32_t)0x01 << itmask;

    if (usartreg == 0x01) /* The IT  is in CR1 register */
    {
        itmask &= LPUARTx->CR1;
    }
    else if (usartreg == 0x02) /* The IT  is in CR2 register */
    {
        itmask &= LPUARTx->CR2;
    }
    else /* The IT  is in CR3 register */
    {
        itmask &= LPUARTx->CR3;
    }

    bitpos = LPUART_IT >> 0x08;
    bitpos = (uint32_t)0x01 << bitpos;
    bitpos &= LPUARTx->SR;
    if ((itmask != (uint32_t)RESET)&&(bitpos != (uint32_t)RESET))
    {
        bitstatus = SET;
    }
    else
    {
        bitstatus = RESET;
    }

    return bitstatus;
}

/**
  * @brief  Clears the LPUARTx's interrupt pending bits.
  * @param  LPUARTx: where x can be 0 to select the LPUART peripheral.
  * @param  LPUART_IT: specifies the interrupt pending bit to clear.
  *          This parameter can be one of the following values:
  *            @arg LPUART_IT_CTSI:  CTS change interrupt
  *            @arg LPUART_IT_TC:   Transmission complete interrupt.
  *            @arg LPUART_IT_RXNE: Receive Data register not empty interrupt.
  *            @arg LPUART_IT_CM: Character match interrupt.
  *            @arg LPUART_IT_WU: Wakeup from stop mode interrupt.
  *            @arg LPUART_IT_IDLE: Idle line detected interrupt.
  *
  * @note   PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun
  *          error) and IDLE (Idle line detected) pending bits are cleared by
  *          software sequence: a read operation to LPUART_SR register
  *          (LPUART_GetITStatus()) followed by a read operation to LPUART_DR register
  *          (LPUART_ReceiveData()).
  * @note   RXNE pending bit can be also cleared by a read to the LPUART_DR register
  *          (LPUART_ReceiveData()).
  * @note   TC pending bit can be also cleared by software sequence: a read
  *          operation to LPUART_SR register (LPUART_GetITStatus()) followed by a write
  *          operation to LPUART_DR register (LPUART_SendData()).
  * @note   TXE pending bit is cleared only by a write to the LPUART_DR register
  *          (LPUART_SendData()).
  *
  * @retval None
  */
void LPUART_ClearITPendingBit(LPUART_TypeDef* LPUARTx, uint32_t LPUART_IT)
{
    uint32_t bitpos = 0x00, itmask = 0x00;
    /* Check the parameters */
    assert_param(IS_LPUART_ALL_PERIPH(LPUARTx));
    assert_param(IS_LPUART_CLEAR_IT(LPUART_IT));

    bitpos = LPUART_IT >> 0x08;
    itmask = ((uint32_t)0x01 << (uint32_t)bitpos);

    if(itmask & 0x3F)
    {
        LPUARTx->DR;
    }
    else if(itmask & 0xC0)
    {
        LPUARTx->DR = 0xFF;
    }
    else
    {
        LPUARTx->SR &= ~itmask;
    }
}

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */



/**
  * @}
  */
